package com.carleasoft.mps.adu.business.org.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carleasoft.mps.adu.business.org.bean.entity.OrgEntity;
import com.carleasoft.mps.adu.business.org.bean.entity.OrganizationType;
import com.carleasoft.mps.adu.business.org.bean.po.OrgTypePo;
import com.carleasoft.mps.adu.business.org.dao.OrganizationTypeDao;
import com.carleasoft.mps.adu.business.org.service.OrgService;
import com.carleasoft.mps.adu.business.org.service.OrganizationTypeService;
import com.carleasoft.mps.adu.common.constants.BusinessErrorEnum;
import com.carleasoft.mps.core.exceptions.BusinessException;
import com.carleasoft.mps.core.user.Constants;
import com.carleasoft.mps.adu.business.org.bean.vo.OrgTypePageQueryVo;
import com.carleasoft.mps.core.user.SortPo;
import com.carleasoft.mps.core.utils.ConvertUtils;
import com.carleasoft.mps.core.utils.DateUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 组织分类表 服务实现类
 * </p>
 *
 * @author ztm
 * @since 2021-09-07
 */
@Service
public class OrganizationTypeServiceImpl extends ServiceImpl<OrganizationTypeDao, OrganizationType> implements OrganizationTypeService {

    @Autowired
    private OrgService orgService;
    @Autowired
    private OrganizationTypeDao organizationTypeDao;

    @Override
    public List<OrgTypePageQueryVo> queryOrganizationType(OrgTypePo orgTypePo) {


        LambdaQueryWrapper<OrganizationType> wrapper = Wrappers.<OrganizationType>lambdaQuery();

        if (StrUtil.isNotBlank(orgTypePo.getOrgTypeName())) {
            wrapper.like(OrganizationType::getOrgTypeName, orgTypePo.getOrgTypeName());
        }
        wrapper.orderByDesc(OrganizationType::getSort);
        wrapper.orderByDesc(OrganizationType::getSortDate);
        List<OrganizationType> organizationTypes = this.list(wrapper);
        if (CollectionUtil.isNotEmpty(organizationTypes)) {
            List<OrgTypePageQueryVo> orgTypePageQueryVos = ConvertUtils.sourceToTarget(organizationTypes, OrgTypePageQueryVo.class);
            return this.buildTree(orgTypePageQueryVos);
        }
        return new ArrayList<>();
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean addOrganizationType(OrganizationType organizationType) {
        //判断是否存在重复数据
        int count = this.count(Wrappers.<OrganizationType>lambdaQuery().eq(OrganizationType::getOrgTypeName, organizationType.getOrgTypeName()));
        if (count > 0) {
            throw new BusinessException(BusinessErrorEnum.ORG_TYPE_NAME_REPEAT);
        }
        String code = IdWorker.getIdStr();
        if (StrUtil.isBlank(organizationType.getParentTypeCode())) {
            organizationType.setParentTypeCode(Constants.PARENT_CODE);
            organizationType.setFullPath(code);
        } else {
            OrganizationType one = this.getOne(Wrappers.<OrganizationType>lambdaQuery().eq(OrganizationType::getOrgTypeCode, organizationType.getParentTypeCode()));
            organizationType.setFullPath(one.getFullPath() + Constants.DELIMITER + code);
        }
        OrganizationType sortType = this.getOne(Wrappers.<OrganizationType>lambdaQuery()
                .eq(OrganizationType::getParentTypeCode, organizationType.getParentTypeCode())
                .orderByDesc(OrganizationType::getSort).last("limit 1"));
        organizationType.setSort(Objects.isNull(sortType) ? 1 : sortType.getSort() + 1);


        organizationType.setOrgTypeCode(code);
        return this.save(organizationType);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean deleteOrganizationType(OrgTypePo orgTypePo) {
        //删除校验
        int count = orgService.count(Wrappers.<OrgEntity>lambdaQuery().eq(OrgEntity::getOrgTypeCode, orgTypePo.getOrgTypeCode()));
        if (count > 0) {
            throw new BusinessException(BusinessErrorEnum.ORG_TYPE_DELETE);
        }
        List<OrganizationType> list = this.list(Wrappers.<OrganizationType>lambdaQuery().like(OrganizationType::getFullPath, orgTypePo.getOrgTypeCode()));
        if (list.size() > 1) {
            throw new BusinessException(BusinessErrorEnum.TYPE_ERROR);
        }
        return this.remove(Wrappers.<OrganizationType>lambdaQuery().eq(OrganizationType::getOrgTypeCode, orgTypePo.getOrgTypeCode()));
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean updateOrganizationType(OrgTypePo orgTypePo) {

        OrganizationType current = this.getOne(Wrappers.<OrganizationType>lambdaQuery().eq(OrganizationType::getOrgTypeCode, orgTypePo.getOrgTypeCode()));
        if (current.getParentTypeCode().equals(orgTypePo.getParentTypeCode())) {
            int count = this.count(Wrappers.<OrganizationType>lambdaQuery().eq(OrganizationType::getOrgTypeName, orgTypePo.getOrgTypeName()));
            if (count > 0) {
                throw new BusinessException(BusinessErrorEnum.ORG_TYPE_NAME_REPEAT);
            }
        }
        if (StrUtil.isNotBlank(orgTypePo.getParentTypeCode()) && current.getParentTypeCode().equals(orgTypePo.getParentTypeCode())) {
            current.setOrgTypeName(orgTypePo.getOrgTypeName());
            return this.update(current, Wrappers.<OrganizationType>lambdaUpdate().eq(OrganizationType::getOrgTypeCode, orgTypePo.getOrgTypeCode()));
        } else if (StrUtil.isBlank(orgTypePo.getParentTypeCode()) && current.getParentTypeCode().equals(Constants.PARENT_CODE)) {
            current.setOrgTypeName(orgTypePo.getOrgTypeName());
            return this.update(current, Wrappers.<OrganizationType>lambdaUpdate().eq(OrganizationType::getOrgTypeCode, orgTypePo.getOrgTypeCode()));
        } else {
            //获取上级全路径

            if (StrUtil.isNotBlank(orgTypePo.getParentTypeCode())) {
                //得到上级分类的详细信息
                OrganizationType parent = this.getOne(Wrappers.<OrganizationType>lambdaQuery().eq(OrganizationType::getOrgTypeCode, orgTypePo.getParentTypeCode()));
                //全路径拼接
                String searchChar = current.getFullPath();
                String newChar = parent.getFullPath() + Constants.DELIMITER + orgTypePo.getOrgTypeCode();
                current.setFullPath(newChar);
                current.setOrgTypeName(orgTypePo.getOrgTypeName());
                current.setParentTypeCode(orgTypePo.getParentTypeCode());
                this.organizationTypeDao.batchUpdateFullPath(searchChar, newChar);

            } else {

                String searchChar = current.getFullPath();
                String newChar = orgTypePo.getOrgTypeCode();
                current.setFullPath(newChar);
                current.setOrgTypeName(orgTypePo.getOrgTypeName());
                current.setParentTypeCode(Constants.PARENT_CODE);
                this.organizationTypeDao.batchUpdateFullPath(searchChar, newChar);
            }
            OrganizationType sortType = this.getOne(Wrappers.<OrganizationType>lambdaQuery()
                    .eq(OrganizationType::getParentTypeCode, current.getParentTypeCode())
                    .orderByDesc(OrganizationType::getSort).last("limit 1"));
            current.setSort(Objects.isNull(sortType) ? 1 : sortType.getSort() + 1);

            return this.update(current, Wrappers.<OrganizationType>lambdaUpdate().eq(OrganizationType::getOrgTypeCode, orgTypePo.getOrgTypeCode()));
        }
    }

    /**
     * 排序修改接口(部门,机构,机构类型的排序都写在了这个接口中)
     *
     * @param sortPo
     * @return
     */
    @Override
    public Boolean updateSort(SortPo sortPo) {
        boolean result = false;
        if (sortPo.getSort() == null) {
            //自己
            OrganizationType own = this.getByCode(sortPo.getOwnCode());
            Integer ownSort = own.getSort();
            Long ownSortDate = own.getSortDate();
            if (StringUtils.isNotEmpty(sortPo.getMoveCode())) {
                OrganizationType down = this.getByCode(sortPo.getMoveCode());
                Integer downSort = down.getSort();
                Long sortDate = down.getSortDate();

                own.setSort(downSort);
                own.setSortDate(sortDate);
                down.setSort(ownSort);
                down.setSortDate(ownSortDate);
                result = this.updateById(own) && this.updateById(down);
            }
        } else {
            LambdaUpdateWrapper<OrganizationType> wrapper = Wrappers.<OrganizationType>lambdaUpdate();
            wrapper.eq(OrganizationType::getOrgTypeCode, sortPo.getOwnCode());
            wrapper.set(OrganizationType::getSortDate, DateUtil.getEpochSecond());
            wrapper.set(OrganizationType::getSort, sortPo.getSort());
            result = this.update(wrapper);
        }
        return result;
    }

    // 通过编码查詢
    private OrganizationType getByCode(String code) {
        LambdaUpdateWrapper<OrganizationType> wrapper = Wrappers.<OrganizationType>lambdaUpdate();
        wrapper.eq(OrganizationType::getOrgTypeCode, code);
        return this.getOne(wrapper);
    }

    //解析并找到父节点
    private List<OrgTypePageQueryVo> buildTree(List<OrgTypePageQueryVo> list) {
        //找出顶级节点编码
        Set<String> pList = list.stream().collect(Collectors.groupingBy(OrgTypePageQueryVo::getParentTypeCode)).keySet();
        Set<String> cList = list.stream().collect(Collectors.groupingBy(OrgTypePageQueryVo::getOrgTypeCode)).keySet();
        List<String> topList = pList.stream().filter(item -> !cList.contains(item)).collect(toList());

        List<OrgTypePageQueryVo> last = new ArrayList<>();
        for (String parentCode : topList) {
            last.addAll(this.getTreeListFromCurrent(parentCode, list));
        }
        return last;
    }

    /**
     * 解析树形数据
     *
     * @param currentId
     * @param entityList
     * @return
     */
    public List<OrgTypePageQueryVo> getTreeListFromCurrent(String currentId, List<OrgTypePageQueryVo> entityList) {

        if (entityList == null || entityList.size() == 0) return new ArrayList<>();

        List<OrgTypePageQueryVo> resultList = new ArrayList<>();

        //获取顶层元素集合
        for (OrgTypePageQueryVo entity : entityList) {
            if (currentId.equals(entity.getParentTypeCode())) {
                resultList.add(entity);
            }
        }

        //获取每个顶层元素的子数据集合
        for (OrgTypePageQueryVo entity : resultList) {
            entity.setChildren(getSubList(entity.getOrgTypeCode(), entityList));
        }
        return resultList;
    }

    /**
     * 获取子数据集合
     *
     * @param subCode
     * @param subList
     */
    private List<OrgTypePageQueryVo> getSubList(String subCode, List<OrgTypePageQueryVo> subList) {
        List<OrgTypePageQueryVo> childList = new ArrayList<>();
        //子集的直接子对象
        for (OrgTypePageQueryVo entity : subList) {
            if (subCode.equals(entity.getParentTypeCode())) {
                childList.add(entity);
            }
        }
        //递归退出条件
        if (childList.size() == 0) {
            return null;
        }
        //子集的间接子对象
        for (OrgTypePageQueryVo entity : childList) {
            entity.setChildren(getSubList(entity.getOrgTypeCode(), subList));
        }

        return childList;
    }

}
